﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;

namespace mijiaxueche.weixin.help
{
    public class HttpHelper
    {
        ///<summary>
        /// 获取指定网页的源码，支持编码自动识别
        ///</summary>
        ///<param name="url"></param>
        ///<returns></returns>
        public static string getDataFromUrl(string url)
        {
            string str = string.Empty;
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);

            //设置http头
            request.AllowAutoRedirect = true;
            request.AllowWriteStreamBuffering = true;
            request.Timeout = 100 * 1000;
            request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";
            //request.Method = "POST";
            request.Accept = "*/*";
            request.Connection = "application/x-www-form-urlencoded";
            //request.KeepAlive = false;

            HttpWebResponse response = null;
            try
            {
                response = (HttpWebResponse)request.GetResponse();
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    //根据http应答的http头来判断编码
                    string characterSet = response.CharacterSet;
                    Encoding encode;
                    if (characterSet != "")
                    {
                        if (characterSet == "ISO-8859-1")
                        {
                            characterSet = "gb2312";
                            //characterSet = "utf-8";
                        }
                        encode = Encoding.GetEncoding(characterSet);
                    }
                    else
                    {
                        encode = Encoding.Default;
                    }

                    //声明一个内存流来保存http应答流
                    Stream receiveStream = response.GetResponseStream();
                    MemoryStream mStream = new MemoryStream();

                    byte[] bf = new byte[255];
                    int count = receiveStream.Read(bf, 0, 255);
                    while (count > 0)
                    {
                        mStream.Write(bf, 0, count);
                        count = receiveStream.Read(bf, 0, 255);
                    }
                    receiveStream.Close();

                    mStream.Seek(0, SeekOrigin.Begin);

                    //从内存流里读取字符串
                    StreamReader reader = new StreamReader(mStream, encode);
                    char[] buffer = new char[1024];
                    count = reader.Read(buffer, 0, 1024);
                    while (count > 0)
                    {
                        str += new String(buffer, 0, count);
                        count = reader.Read(buffer, 0, 1024);
                    }

                    //从解析出的字符串里判断charset，如果和http应答的编码不一直
                    //那么以页面声明的为准，再次从内存流里重新读取文本
                    Regex reg =
                        new Regex(@"<meta[\s\S]+?charset=(.*)""[\s\S]+?>",
                                  RegexOptions.Multiline | RegexOptions.IgnoreCase);
                    MatchCollection mc = reg.Matches(str);
                    if (mc.Count > 0)
                    {
                        string tempCharSet = mc[0].Result("$1");
                        if (string.Compare(tempCharSet, characterSet, true) != 0)
                        {
                            encode = Encoding.GetEncoding(tempCharSet);
                            str = string.Empty;
                            mStream.Seek(0, SeekOrigin.Begin);
                            reader = new StreamReader(mStream, encode);
                            buffer = new char[255];
                            count = reader.Read(buffer, 0, 255);
                            while (count > 0)
                            {
                                str += new String(buffer, 0, count);
                                count = reader.Read(buffer, 0, 255);
                            }
                        }
                    }
                    reader.Close();
                    mStream.Close();
                }
            }
            catch (Exception ex)
            {
                //throw ex;
                Trace.TraceError(ex.ToString());
            }
            finally
            {
                if (response != null)
                    response.Close();
            }
            return str;
        }

        /// <summary>
        /// 可以自动解压支持编码自动识别 默认 gb2312编码
        /// </summary>
        /// <param name="url"></param>
        /// <param name="chart">指定编码格式，为空则自动识别</param>
        /// <returns></returns>
        public static string GetGZipEncodedHTMLContent(string url, string chart)
        {
            try
            {
                Uri targetUri = new Uri(url);
                HttpWebRequest wr = (HttpWebRequest)HttpWebRequest.Create(targetUri);
                //设置http头
                wr.AllowAutoRedirect = true;
                wr.AllowWriteStreamBuffering = true;
                wr.Timeout = 10 * 1000;
                wr.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1;WOW64; Trident/6.0;SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C;.NET4.0E)";
                //wr.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";
                //wr.Method = "POST";
                wr.Accept = "*/*";
                wr.Connection = "application/x-www-form-urlencoded";

                HttpWebResponse wsp = (HttpWebResponse)wr.GetResponse();
                Stream st = wsp.GetResponseStream();
                if (wsp.ContentEncoding.ToLower().Contains("gzip"))
                {
                    st = new GZipStream(st, CompressionMode.Decompress);
                }

                //根据http应答的http头来判断编码
                string characterSet = "";
                if (chart == "")
                {
                    characterSet = wsp.CharacterSet;
                }
                else
                {
                    characterSet = chart;
                }
                Encoding encode;
                if (characterSet != "")
                {
                    if (characterSet == "ISO-8859-1")
                    {
                        characterSet = "gb2312";//gb2312
                    }
                    encode = Encoding.GetEncoding(characterSet);
                }
                else
                {
                    encode = Encoding.Default;
                }
                StreamReader sr = new StreamReader(st, encode);
                string result = sr.ReadToEnd();
                Regex r = new Regex("(?<=charset[=])([\\s\\S]{3,}?)(?=(\"|$))");
                MatchCollection mc = r.Matches(result);
                if (mc != null && mc.Count > 0)
                {
                    characterSet = mc[0].ToString().Replace("\\", "").Replace("\"", "").ToLower();
                    if (characterSet == "utf-8" && characterSet != encode.BodyName.ToLower())	 //解决部分网页的乱码问题
                    {
                        result = GetGZipEncodedHTMLContent(url, characterSet);
                    }
                }

                return result;
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                return ex.ToString();
            }
        }

        /// <summary>  
        /// Post 提交调用抓取  
        /// </summary>  
        /// <param name="url">提交地址</param>  
        /// <param name="param">参数</param>  
        /// <returns>string</returns>  
        public static string webRequestPost(string url, string param)
        {

            //param = System.Web.HttpUtility.UrlEncode(param,Encoding.UTF8);
            //param.Replace("(", "%28").Replace(")","%29");
            byte[] bs = System.Text.Encoding.UTF8.GetBytes(param);

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url /*+ "?" + param*/);
            req.Method = "Post";
            req.Timeout = 120 * 1000;
            req.ContentType = "application/x-www-form-urlencoded;";
            req.ContentLength = bs.Length;

            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
                reqStream.Flush();
            }
            using (WebResponse wr = req.GetResponse())
            {
                //在这里对接收到的页面内容进行处理   

                Stream strm = wr.GetResponseStream();
                StreamReader sr = new StreamReader(strm, System.Text.Encoding.UTF8);
                string line;

                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                while ((line = sr.ReadLine()) != null)
                {
                    sb.Append(line + System.Environment.NewLine);
                }
                sr.Close();
                strm.Close();
                return sb.ToString();
            }
        }

    }
}
